<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Loop (files &amp; folders)</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
</head>
<body>

<h1>Loop (files &amp; folders)</h1>

<p>Retrieves the specified files or folders, one at a time.</p>

<pre class="Syntax">Loop, Files, FilePattern [, Mode]  <em>; v1.1.21+ (recommended)</em></pre>
<pre class="Syntax">Loop, FilePattern [, IncludeFolders?, Recurse?]</pre>
<h3>Parameters</h3>
<dl>

  <dt>Files <span class="ver">[v1.1.21+]</span></dt>
  <dd><p>The literal word <code>Files</code> (case-insensitive). This cannot be a variable or expression.</p></dd>

  <dt>FilePattern</dt>
  <dd><p>The name of a single file or folder, or a wildcard pattern such as <code>C:\Temp\*.tmp</code>. <em>FilePattern</em> is assumed to be in <a href="../Variables.htm#WorkingDir">%A_WorkingDir%</a> if an absolute path isn't specified.</p>
    <p>Both asterisks and question marks are supported as wildcards. A match occurs when the pattern appears in either the file's long/normal name or its <a href="#LoopFileShortName">8.3 short name</a>.</p>
    <p>If this parameter is a single file or folder (i.e. no wildcards) and <em>Recurse</em> is set to 1 or <em>Mode</em> includes <code>R</code>, more than one match will be found if the specified file name appears in more than one of the folders being searched.</p></dd>

  <dt>Mode <span class="ver">[v1.1.21+]</span></dt>
  <dd><p>Zero or more of the following letters:</p>
    <p><code>D</code>: Include directories (folders).<br>
    <code>F</code>: Include files. Files are also included if both F and D are omitted.<br>
    <code>R</code>: Recurse into subdirectories (subfolders). If R is omitted, files and folders in subfolders are not included.</p>
  </dd>

  <dt>IncludeFolders?</dt>
  <dd><p>One of the following digits, or blank to use the default:<br>
      0 (default) Folders are not retrieved (only files).<br>
  1 All files and folders that match the wildcard pattern are retrieved.<br>
  2 Only folders are retrieved (no files).</p></dd>
  
  <dt>Recurse?</dt>
  <dd>One of the following digits, or blank to use the default:<br>
      0 (default) Subfolders are not recursed into.<br>
1 Subfolders are recursed into so that files and folders contained therein are retrieved if they match <em>FilePattern</em>. All subfolders will be recursed into, not just those whose names match <em>FilePattern</em>.</dd>

</dl>

<h3>Special Variables Available Inside a File-Loop</h3>
<p>The following variables exist within any file-loop. If an inner file-loop is enclosed by an outer file-loop, the innermost loop's file will take precedence:</p>
<table class="info">
  <tr>
    <td>A_LoopFileName</td>
    <td><a name="LoopFileName" id="LoopFileName"></a>The name of the file or folder currently retrieved (without the path).</td>
  </tr>
  <tr>
    <td><a name="LoopFileExt"></a>A_LoopFileExt</td>
    <td>The file's extension (e.g. TXT, DOC, or EXE). The period (.) is not included.</td>
  </tr>
  <tr>
    <td>A_LoopFileFullPath</td>
    <td><a name="LoopFileFullPath"></a>The path and name of the file/folder currently retrieved. If <em>FilePattern</em> contains a relative path rather than an absolute path, the path here will also be relative. In addition, any short (8.3) folder names in <em>FilePattern</em> will still be short (see next item to get the long version).</td>
  </tr>
  <tr>
    <td>A_LoopFileLongPath</td>
    <td><a name="LoopFileLongPath"></a>This is different than A_LoopFileFullPath in the following ways: 1) It always contains the absolute/complete path of the file even if <em>FilePattern</em> contains a relative path; 2) Any short (8.3) folder names in <em>FilePattern</em> itself are converted to their long names; 3) Characters in <em>FilePattern</em> are converted to uppercase or lowercase to match the case stored in the file system. This is useful for converting file names -- such as those passed into a script as command line parameters -- to their exact path names as shown by Explorer.</td>
  </tr>
  <tr>
    <td>A_LoopFileShortPath</td>
    <td><p><a name="LoopFileShortPath"></a>The 8.3 short path and name of the file/folder currently retrieved. For example: C:\MYDOCU~1\ADDRES~1.txt. If <em>FilePattern</em> contains a relative path rather than an absolute path, the path here will also be relative.</p>
      <p>To retrieve the complete 8.3 path and name for a single file or folder, specify its name for <em>FilePattern</em> as in this example:</p>
<pre>Loop, C:\My Documents\Address List.txt
    ShortPathName = %A_LoopFileShortPath%</pre>
        <p>NOTE: This variable will be <strong>blank</strong> if the file does not have a short name, which can happen on systems where NtfsDisable8dot3NameCreation has been set in the registry. It will also be blank if FilePattern contains a relative path and the body of the loop uses <a href="SetWorkingDir.htm">SetWorkingDir</a> to switch away from the working directory in effect for the loop itself.</p></td>
  </tr>
  <tr>
    <td>A_LoopFileShortName</td>
    <td><a name="LoopFileShortName"></a>The 8.3 short name, or alternate name of the file. If the file doesn't have one (due to the long name being shorter than 8.3 or perhaps because short-name generation is disabled on an NTFS file system), <em>A_LoopFileName</em> will be retrieved instead.</td>
  </tr>
  <tr>
    <td>A_LoopFileDir</td>
    <td><a name="LoopFileDir"></a>The path of the directory in which <em>A_LoopFileName</em> resides. If <em>FilePattern</em> contains a relative path rather than an absolute path, the path here will also be relative. A root directory will not contain a trailing backslash. For example: C:</td>
  </tr>
  <tr>
    <td>A_LoopFileTimeModified</td>
    <td><a name="LoopFileTimeModified"></a>The time the file was last modified. Format <a href="FileSetTime.htm">YYYYMMDDHH24MISS</a>.</td>
  </tr>
  <tr>
    <td>A_LoopFileTimeCreated</td>
    <td><a name="LoopFileTimeCreated"></a>The time the file was created. Format <a href="FileSetTime.htm">YYYYMMDDHH24MISS</a>.</td>
  </tr>
  <tr>
    <td>A_LoopFileTimeAccessed</td>
    <td><a name="LoopFileTimeAccessed"></a>The time the file was last accessed. Format <a href="FileSetTime.htm">YYYYMMDDHH24MISS</a>.</td>
  </tr>
  <tr>
    <td>A_LoopFileAttrib</td>
    <td><a name="LoopFileAttrib"></a>The <a href="FileGetAttrib.htm">attributes</a> of the file currently retrieved.</td>
  </tr>
  <tr>
    <td>A_LoopFileSize</td>
    <td><a name="LoopFileSize"></a>The size in bytes of the file currently retrieved. Files larger than 4 gigabytes are also supported.</td>
  </tr>
  <tr>
    <td>A_LoopFileSizeKB</td>
    <td><a name="LoopFileSizeKB"></a>The size in Kbytes of the file currently retrieved, rounded down to the nearest integer.</td>
  </tr>
  <tr>
    <td>A_LoopFileSizeMB</td>
    <td><a name="LoopFileSizeMB"></a>The size in Mbytes of the file currently retrieved, rounded down to the nearest integer.</td>
  </tr>
</table>
<h3>Remarks</h3>
<p>A file-loop is useful when you want to operate on a collection of files and/or folders, one at a time.</p>
<p>All matching files are retrieved, including hidden files. By contrast, OS features such as the DIR command omit hidden files by default. To avoid processing hidden, system, and/or read-only files, use something like the following inside the loop:</p>
<pre>if A_LoopFileAttrib contains H,R,S  <em>; Skip any file that is either H (Hidden), R (Read-only), or S (System). Note: No spaces in &quot;H,R,S&quot;.</em>
    continue  <em>; Skip this file and move on to the next one.</em></pre>
<p>To retrieve files' relative paths instead of absolute paths during a recursive search, use <a href="SetWorkingDir.htm">SetWorkingDir</a> to change to the base folder prior to the loop, and then omit the path from the Loop (e.g. <code>Loop, *.*, 0, 1</code>). That will cause <a href="#LoopFileFullPath">A_LoopFileFullPath</a> to contain the file's path relative to the base folder.</p>
<p>A file-loop can disrupt itself if it creates or renames files or folders within its own purview. For example, if it renames files via <a href="FileMove.htm">FileMove</a> or other means, each such file might be found twice: once as its old name and again as its new name. To work around this, rename the files only after creating a list of them. For example:</p>
<pre>FileList =
Loop, Files, *.jpg
   FileList = %FileList%%A_LoopFileName%`n
Loop, Parse, FileList, `n
   FileMove, %A_LoopField%, renamed_%A_LoopField%</pre>
<p>Files in an NTFS file system are probably always retrieved in alphabetical order. Files in other file systems are retrieved in no particular order. To ensure a particular ordering, use the <a href="Sort.htm">Sort</a> command as shown in the Examples section below.</p>
<p>Files and folders with a complete path name longer than 259 characters are skipped over as though they do not exist. Such files are rare because normally, the operating system does not allow their creation.</p>
<p>See <a href="Loop.htm">Loop</a> for information about <a href="Block.htm">Blocks</a>, <a href="Break.htm">Break</a>, <a href="Continue.htm">Continue</a>, and the A_Index variable (which exists in every type of loop).</p>
<h3>Related</h3>
<p><a href="Loop.htm">Loop</a>, <a href="Break.htm">Break</a>, <a href="Continue.htm">Continue</a>, <a href="Block.htm">Blocks</a>, <a href="SplitPath.htm">SplitPath</a>, <a href="FileSetAttrib.htm">FileSetAttrib</a>, <a href="FileSetTime.htm">FileSetTime</a></p>
<h3>Examples</h3>
<pre class="NoIndent"><em>; Example #1:</em>
Loop Files, %A_ProgramFiles%\*.txt, R  <em>; Recurse into subfolders.</em>
{
    MsgBox, 4, , Filename = %A_LoopFileFullPath%`n`nContinue?
    IfMsgBox, No
        break
}</pre>
<p>&nbsp;</p>
<pre class="NoIndent"><em>; Example #2: Calculate the size of a folder, including the files in all its subfolders:</em>
SetBatchLines, -1  <em>; Make the operation run at maximum speed.</em>
FolderSizeKB = 0
FileSelectFolder, WhichFolder  <em>; Ask the user to pick a folder.</em>
Loop, Files, %WhichFolder%\*.*, R
    FolderSizeKB += %A_LoopFileSizeKB%
MsgBox Size of %WhichFolder% is %FolderSizeKB% KB.</pre>
<p>&nbsp;</p>
<pre class="NoIndent"><em>; Example #3: Retrieve file names sorted by name (see next example to sort by date):</em>
FileList =  <em>; Initialize to be blank.</em>
Loop, C:\*.*
    FileList = %FileList%%A_LoopFileName%`n
Sort, FileList, R  <em>; The R option sorts in reverse order. See <a href="Sort.htm">Sort</a> for other options.</em>
Loop, parse, FileList, `n
{
    if A_LoopField =  <em>; Ignore the blank item at the end of the list.</em>
        continue
    MsgBox, 4,, File number %A_Index% is %A_LoopField%.  Continue?
    IfMsgBox, No
        break
}</pre>
<p>&nbsp;</p>
<pre class="NoIndent"><em>; Example #4: Retrieve file names sorted by modification date:</em>
FileList =
Loop, Files, %A_MyDocuments%\Photos\*.*, FD  <em>; Include Files and Directories</em>
    FileList = %FileList%%A_LoopFileTimeModified%`t%A_LoopFileName%`n
Sort, FileList  <em>; Sort by date.</em>
Loop, Parse, FileList, `n
{
    if A_LoopField =  <em>; Omit the last linefeed (blank item) at the end of the list.</em>
        continue
    StringSplit, FileItem, A_LoopField, %A_Tab%  <em>; Split into two parts at the tab char.</em>
    MsgBox, 4,, The next file (modified at %FileItem1%) is:`n%FileItem2%`n`nContinue?
    IfMsgBox, No
        break
}</pre>
<p>&nbsp;</p>
<pre class="NoIndent"><em>; Example #5: Copy only the source files that are newer than their counterparts
; in the destination:</em>
CopyIfNewer:
<em>; Caller has set the variables CopySourcePattern and CopyDest for us.</em>
Loop, Files, %CopySourcePattern%
{
    copy_it = n
    IfNotExist, %CopyDest%\%A_LoopFileName%  <em>; Always copy if target file doesn't yet exist.</em>
        copy_it = y
    else
    {
        FileGetTime, time, %CopyDest%\%A_LoopFileName%
        EnvSub, time, %A_LoopFileTimeModified%, seconds  <em>; Subtract the source file's time from the destination's.</em>
        if time &lt; 0  <em>; Source file is newer than destination file.</em>
            copy_it = y
    }
    if copy_it = y
    {
        FileCopy, %A_LoopFileFullPath%, %CopyDest%\%A_LoopFileName%, 1   <em>; Copy with overwrite=yes</em>
        if ErrorLevel
            MsgBox, Could not copy &quot;%A_LoopFileFullPath%&quot; to &quot;%CopyDest%\%A_LoopFileName%&quot;.
    }
}
Return</pre>
<p>&nbsp;</p>
<pre class="NoIndent"><em>; Example #6: Convert filenames passed in via command-line parameters to long names,
; complete path, and correct uppercase/lowercase characters as stored in the file system.</em>
Loop %0%  <em>; For each file dropped onto the script (or passed as a parameter).</em>
{
    GivenPath := %A_Index%  <em>; Retrieve the next command line parameter.</em>
    Loop %GivenPath%, 1
        LongPath = %A_LoopFileLongPath%
    MsgBox The case-corrected long path name of file`n%GivenPath%`nis:`n%LongPath%
}</pre>

</body>
</html>
